当我们考虑怎么逻辑地组织数据时,应该将一个人的所有信息项放在一起,即保持相关性。
一旦定义了一个结构体类型的变量,系统在分配内存时就会分配一块连续的空间,依次存放它的每一个分量。这块空间总的名字就是结构体变量的名字。内部还有各自的名字
引入结构体有什么好处?
引入结构体可以将一组逻辑上相关的变量组合成一个有机的整体,表达更复杂的对象。
单链表中为什么要引入头结点?
消除插入或删除第一个结点的特殊情况。
结构体类型定义的作用是什么?结构体类型的变量定义的作用是什么?
结构体类型定义是告诉C++这种类型的变量是如何组成的,需要多少空间。结构体变量的定义是告诉C++程序中需要存储和处理一个某结构体类型的变量,这时C++根据结构体类型的定义为这个变量分配空间。
结构体类型允许程序员把一些分量聚合成一个整体,用一个变量表示。
一个结构体的各个分量都有名字,把这些分量称为成员(member)。
由于结构体的成员可以是各种类型的,程序员能创建适合于问题的数据聚合。
一旦定义了一个结构体类型的变量,系统在分配内存时就会分配一块连续的空间,依次存放它的每一个分量。这块空间总的名字就是结构体变量的名字。内部还有各自的名字。
可以在定义结构体类型的同时定义指向结构体的指针或变量。
结构体类型是存储空间尺寸的描述,不会预先分配内存空间。
对于批量数据,一个形式是数组,如一年12个月的天数,有存储的规律性或叫连续性,通过数组下标体现出来(通过数组名和下标访问)。另一个形式是结构体,可以将多个数据集中到同一个对象,当然也是集中存储,但数据的访问通过属性体现出来(通过结构体实例名+属性名访问)。
另一种批量数据处理的方式:链表,通过指针将单个数据连续起来。
结构体实例化的元素与对象的属性其实质也是变量,只是其隶属于某个集合而已。
结构体变量名是大内存空间的地址,则元素是其中小内存空间的地址。
结构是一个或多个变量的集合,该集合有一个单独的名称,便于操作。与数组不同,结构可以储存不同类型(C语言的任意数据类型,包括数组和其他结构)的变量。结构中的变量被称为结构的成员(member)。
int arr[]={1,2,3,5,6};sizeof(arr);测试的是整个数组所占用的字节数,其长度可以写成:sizeof(arr)/sizeof(arr[0])
C遵循的基本的内存布局假设:通过对象的基地址和数据成员的偏移量获取数据成员的地址。
基本数据类型:其值不可以理解为其它类型,也就是说,它是自我说明的;
构造数据类型:由若干成员或元素(基本数据类型或构造数据类型)构成的复合数据类型,分为数组类型、结构类型、联合类型;
编译器会自动对齐结构体数据成员以提高运行效率;
第一个成员的地址与整个结构的地址相同;
如果不使用构造函数也是可以的,只定义一般的结构体,里面包含两个参数:
struct Node{
……int u,step; // u为顶点,step为源点到顶点u的最短路径
};
那么在变量参数赋值时,需要这样赋值:
Node vs ; //先定义一个Node结点类型变量
vs.u =3 ,vs.step = 5; //分别对该变量的两个成员进行赋值
采用构造函数的形式定义结构体:
struct Node{ int u,step; Node(){}; Node(int a,int sp){ u = a; //参数传递u为顶点 step = sp; //参数传递step为源点到顶点u的最短路径 } };
则变量参数赋值就可以直接通过参数传递:
Node vs(3,5)
上面语句等价于:
vs.v =3 ,vs.step = 5;
C11允许采用(type_name){xx,xx,xx} 类似于 C++ 的构造函数的形式构造匿名的结构体。复合字面量:初始化结构的时候允许对特定的元素赋值,形式为:
struct test { int a[3],b; } foo[] = { [0].a = {1}, [1].a = 2 }; struct test{int a, b, c, d;} foo = { .a = 1, .c = 3, 4, .b = 5 }; // 3,4 是对 .c,.d 赋值的
储存一年来看过的所有电影的信息,应该用什么样的数据结构:用一个结构体存储一部电影的所有信息,用一个数组来存储看过的电影。也就是数组元素是结构体,表示电影信息。如果想储存不同用户的数据呢?数组表示用户,用数组的数组存储,最后的元素是结构体。
union one4all { int int_val; long long_val; double double_val; }; one4all pail; pail.int_val = 15; pail.double_val = 3.14; // at this time, int value is lost
在C++中,结构体是纯数据的定义,如果还涉及到这些数据的操作,则更建议考虑类类型;
结构体和类都是对基本类型的扩展,用于提高编程的颗粒度;
A union is a data format that can hold different data types but only one type at a time.
union one4all { int int_val; long long_val; double double_val; }; one4all pail; pail.int_val = 15; // store an int cout << pail.int_val; pail.double_val = 1.38; // store a double, int value is lost cout << pail.double_val;
A union can hold a single value, but it can be of a variety of types, with the member name indicating which mode is being used.
结构体的字节对齐是指编译器在为结构体变量分配内存时,保证下一个成员的偏移量为成员类型的整数倍。因此,对于一些结构体变量来说,其大小并不等于结构体中每一个成员大小的总和。
结构体是一组变量的集合,它能够将不同数据类型的对象组合为一个整体,以描述一个新的对象。例如,描述一个学生信息。学生信息需要包括姓名、年龄、性别、地址等信息。这样,由姓名、年龄、性别、地址等内容就构成了学生对象。在程序中为了描述类似于“学生”这样的复合对象(由多个成分构成),可以使用结构体类型。在C++中,结构体类型的声明使用struct关键字。
两个结构体变量之间是否可以相互赋值呢?答案是可以的。
编译器在为结构体变量分配空间时,保证下一个成员的偏移量应为该成员数据类型长度的整数倍。
共用体类型提供了一种机制,使得多个变量(公用体中的成员)可以共享同一个内存地址。
当定义一个共用体变量时,编译器会根据共用体成员中占用最多内存空间的变量分配空间,这样使得共用体中所有成员的都能够获得足够的空间。
C语言中通过定义由基本数据类型组合而成的“构造数据类型”表示这种集合数据。构造数据类型有数组、结构体、共用体三种类型。
共用体类型数据的特点
(1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。
(2) 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。
(3) 共用体变量的地址和它的各成员的地址都是同一地址。
设有若干个人员的数据,其中有学生和教师。
学生:姓名、号码、性别、职业、班级。
教师:姓名、号码、性别、职业、职务。
struct { int num; char name[10]; char sex; char job; union { int banji; char position[10]; }category; }person[2];/*先设人数为2*/
设有若干个人员的数据,其中有学生和教师。学生的数据中包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、号码、性别、职业、职务。可以看出,学生和教师所包含的数据是不同的。现要求把它们放在同一表格中,即可以使用共同体。
struct{ int num; char name[10]; char sex; char job; union { int banji; char position[10]; }category; }person[2];/*先设人数为2*/
C语言并没有多维数组,因为内存是一种线性存在,即便是多维数组也是实现成一维数组的形式。
就多维数组在这里解释一下。所谓多维数组就是将若干个降一维的数组组合在一起,降一维的数组又由若干个更降一维的数组组合在一起,直到最低的一维数组。
[]便是指针运算的语法糖。
观察到多维数组的遍历中我们和平时的做法有些不同,是先对i进行遍历,再对j进行遍历,这就导致了程序必须在内存块中无规律的跳动,这里的无规律是计算机认为的无规律,虽然在我们看来的确是有迹可寻,优秀的编译器能够对它进行优化处理。就事论事,即这段程序的空间局部性比较差,对于一个在内存中大幅度跳跃,无规律跳跃的程序都将影响程序的性能。这个判定对于一个连续的内存块来说是很重要的,比如C语言中的结构体(内存对齐也是希望实现一种有规律的跳动)。
Arrays allow us to store and access many variables of the same type through a single identifier. Array elements can be accessed using the subscript operator ([]). Be careful not to index an array out of the array’s range. Arrays can be initialized using an initializer list or uniform initialization (in C++11).
Fixed arrays must have a length that is set at compile time. Fixed arrays will usually decay into a pointer when evaluated or passed to a function.